package com.neusoft.hifly.push.mobile.util;

import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;

import com.neusoft.hifly.push.mobile.domain.JPushModelObj;
import cn.jiguang.common.ClientConfig;
import cn.jiguang.common.resp.APIConnectionException;
import cn.jiguang.common.resp.APIRequestException;
import cn.jpush.api.JPushClient;
import cn.jpush.api.push.PushResult;
import cn.jpush.api.push.model.Message;
import cn.jpush.api.push.model.Options;
import cn.jpush.api.push.model.Platform;
import cn.jpush.api.push.model.PushPayload;
import cn.jpush.api.push.model.audience.Audience;
import cn.jpush.api.push.model.audience.AudienceTarget;
import cn.jpush.api.push.model.notification.AndroidNotification;
import cn.jpush.api.push.model.notification.IosNotification;
import cn.jpush.api.push.model.notification.Notification;

/**
 * Title: 消息推送中间件
 * <p>
 * Description: 推送发送消息的方法类
 * <p>
 * Copyright: 2019
 * <p>
 * Company: 东软汉枫
 *
 * @author lh_neu
 * @version 1.0.0
 */
public class JGPushUtil {
	// 极光推送的配置类
	private ClientConfig clientConfig;
	// 极光推送的客户端类
	private static JPushClient jPushClient;

	/**
	 * 构造方法,来初始化极光推送的配置类和实现类
	 *
	 * @param masterSecret
	 *            极光推送MasterSecret
	 * @param appKey
	 *            极光推送AppKey
	 */
	public JGPushUtil(final String masterSecret, final String appKey) {
		if (clientConfig == null) {
			clientConfig = ClientConfig.getInstance();

			// 最大重试次数
			clientConfig.setMaxRetryTimes(5);
			// 连接超时时间，暂定30秒
			clientConfig.setConnectionTimeout(30 * 1000);

			if (JGPushUtil.jPushClient == null) {
				JGPushUtil.jPushClient = new JPushClient(masterSecret, appKey, null, clientConfig);
			}
		}
	}

	/**
	 * 某些平台，所有设备，内容为 ALERT 的通知。
	 *
	 * @param platforms
	 *            某些平台(android,iOS),多个平台用,分隔
	 * @param alert
	 *            推送消息内容
	 * @param pushType
	 *            推送环境类型(生产环境还是正式环境) release为正式环境，debug为生产环境
	 * @param extras
	 *            推送扩展参数map集合
	 * @return 推送结果
	 * @throws APIConnectionException
	 *             Exception
	 * @throws APIRequestException
	 *             Exception
	 */
	public PushResult buildPushObject_some_all_alert(final String platforms, final String alert, final String pushType,
			final Map<String, String> extras) throws APIConnectionException, APIRequestException {
		final PushPayload pushPayload = PushPayload.newBuilder().setPlatform(getPlatforms(platforms))
				.setAudience(Audience.all())
				.setNotification(Notification.newBuilder().setAlert(alert)
						.addPlatformNotification(AndroidNotification.newBuilder().addExtras(extras).build())
						.addPlatformNotification(IosNotification.newBuilder().addExtras(extras).build()).build())
				.setOptions(Options.newBuilder().setApnsProduction(getIsProduce(pushType)).build()).build();

		return JGPushUtil.jPushClient.sendPush(pushPayload);
	}

	/**
	 * 某些平台，推送目标是别名为 alias的集合，通知内容为 ALERT
	 *
	 * @param platforms
	 *            某些平台(android,iOS),多个平台用,分隔
	 * @param alias
	 *            推送群体别名集合
	 * @param alert
	 *            推送消息内容
	 * @param pushType
	 *            推送环境类型(生产环境还是正式环境) release为正式环境，debug为生产环境
	 * @param extras
	 *            推送扩展参数map集合
	 * @return 推送结果
	 * @throws APIConnectionException
	 *             Exception
	 * @throws APIRequestException
	 *             Exception
	 */
	public PushResult buildPushObject_some_alias_alert(final String platforms, final List<String> alias,
			final String alert, final String pushType, final Map<String, String> extras)
			throws APIConnectionException, APIRequestException {
		final PushPayload pushPayload = PushPayload.newBuilder().setPlatform(getPlatforms(platforms))
				.setAudience(Audience.alias(alias))
				.setNotification(Notification.newBuilder().setAlert(alert)
						.addPlatformNotification(AndroidNotification.newBuilder().addExtras(extras).build())
						.addPlatformNotification(IosNotification.newBuilder().addExtras(extras).build()).build())
				.setOptions(Options.newBuilder().setApnsProduction(getIsProduce(pushType)).build()).build();

		return JGPushUtil.jPushClient.sendPush(pushPayload);
	}

	/**
	 * 某些平台，推送目标是标签名为 tags的集合，通知内容为 ALERT
	 *
	 * @param platforms
	 *            某些平台(android,iOS),多个平台用,分隔
	 * @param tagsList
	 *            推送群体标签名集合
	 * @param alert
	 *            推送消息内容
	 * @param pushType
	 *            推送环境类型(生产环境还是正式环境) release为正式环境，debug为生产环境
	 * @param extras
	 *            推送扩展参数map集合
	 * @return 推送结果
	 * @throws APIConnectionException
	 *             Exception
	 * @throws APIRequestException
	 *             Exception
	 */
	public PushResult buildPushObject_some_tags_alert(final String platforms, final List<String> tagsList,
			final String alert, final String pushType, final Map<String, String> extras)
			throws APIConnectionException, APIRequestException {
		final PushPayload pushPayload = PushPayload.newBuilder().setPlatform(getPlatforms(platforms))
				.setAudience(Audience.tag(tagsList))
				.setNotification(Notification.newBuilder().setAlert(alert)
						.addPlatformNotification(AndroidNotification.newBuilder().addExtras(extras).build())
						.addPlatformNotification(IosNotification.newBuilder().addExtras(extras).build()).build())
				.setOptions(Options.newBuilder().setApnsProduction(getIsProduce(pushType)).build()).build();

		return JGPushUtil.jPushClient.sendPush(pushPayload);
	}

	/**
	 * 构建推送对象：平台是 Android，目标是 tag 为 tagName 的设备，内容是 Android 通知 ALERT，并且标题为 TITLE。
	 *
	 * @param tagName
	 *            标签
	 * @param title
	 *            名称
	 * @param alert
	 *            推送消息内容
	 * @return 推送结果
	 * @throws APIConnectionException
	 *             Exception
	 * @throws APIRequestException
	 *             Exception
	 */
	public PushResult buildPushObject_android_tag_alertWithTitle(final String tagName, final String title,
			final String alert) throws APIConnectionException, APIRequestException {
		final PushPayload pushPayload = PushPayload.newBuilder().setPlatform(Platform.android())
				.setAudience(Audience.tag(tagName)).setNotification(Notification.android(alert, title, null)).build();

		return JGPushUtil.jPushClient.sendPush(pushPayload);
	}

	/**
	 * 构建推送对象：平台是 iOS，推送目标是 "tag1", "tag_all" 的交集， 推送内容同时包括通知与消息 - 通知信息是 ALERT，角标数字为 5，通知声音为 "happy"， 并且附加字段 from =
	 * "JPush"；消息内容是 MSG_CONTENT。 通知是 APNs 推送通道的，消息是 JPush 应用内消息通道的。 APNs 的推送环境是“生产”（如果不显式设置的话，Library 会默认指定为开发
	 *
	 * @param tagName1
	 *            标签
	 * @param tagName2
	 *            标签
	 * @param alert
	 *            推送消息内容
	 * @param meg_content
	 *            内容
	 * @return 推送结果
	 * @throws APIConnectionException
	 *             Exception
	 * @throws APIRequestException
	 *             Exception
	 */
	public PushResult buildPushObject_ios_tagAnd_alertWithExtrasAndMessage(final String tagName1, final String tagName2,
			final String alert, final String meg_content) throws APIConnectionException, APIRequestException {
		final PushPayload pushPayload = PushPayload.newBuilder().setPlatform(Platform.ios())
				.setAudience(Audience.tag_and(tagName1, tagName2))
				.setNotification(Notification.newBuilder()
						.addPlatformNotification(IosNotification.newBuilder().setAlert(alert).setBadge(5)
								.setSound("happy").addExtra("from", "JPush").build())
						.build())
				.setMessage(Message.content(meg_content))
				.setOptions(Options.newBuilder().setApnsProduction(true).build()).build();

		return JGPushUtil.jPushClient.sendPush(pushPayload);
	}

	/**
	 * 构建推送对象：平台是 Andorid 与 iOS，推送目标是 （"tag1" 与 "tag2" 的并集）交（"alias1" 与 "alias2" 的并集）， 推送内容是 - 内容为 MSG_CONTENT
	 * 的消息，并且附加字段 from = JPush。
	 *
	 * @param tag1
	 *            目标
	 * @param tag2
	 *            目标
	 * @param alias1
	 *            别名
	 * @param alias2
	 *            别名
	 * @param msg_content
	 *            内容
	 * @return 推送结果
	 * @throws APIConnectionException
	 *             Exception
	 * @throws APIRequestException
	 *             Exception
	 */
	public PushResult buildPushObject_ios_audienceMore_messageWithExtras(final String tag1, final String tag2,
			final String alias1, final String alias2, final String msg_content)
			throws APIConnectionException, APIRequestException {
		final PushPayload pushPayload = PushPayload.newBuilder().setPlatform(Platform.android_ios())
				.setAudience(Audience.newBuilder().addAudienceTarget(AudienceTarget.tag(tag1, tag2))
						.addAudienceTarget(AudienceTarget.alias(alias1, alias2)).build())
				.setMessage(Message.newBuilder().setMsgContent(msg_content).addExtra("from", "JPush").build()).build();

		return JGPushUtil.jPushClient.sendPush(pushPayload);
	}

	/**
	 * 根据平台字符串获得需要推送的平台
	 *
	 * @param platforms
	 *            平台字符
	 * @return 平台
	 */
	private Platform getPlatforms(final String platforms) {
		// 推送平台为空，默认为全平台(android、iOS)
		Platform platform = Platform.all();
		if (StringUtils.isNotEmpty(platforms)) {
			if (StringUtils.equals(JPushModelObj.PLATFORM_ANDROID, platforms)) {
				platform = Platform.android();
			} else if (StringUtils.equals(JPushModelObj.PLATFORM_IOS, platforms)) {
				platform = Platform.ios();
			} else if (StringUtils.equals(JPushModelObj.PLATFORM_ANDROID_AND_IOS, platforms)
					|| StringUtils.equals("iOS,android", platforms)) {
				platform = Platform.android_ios();
			}
		}

		return platform;
	}

	/**
	 * 根据推送环境字符串判断是生产环境还是正式环境
	 *
	 * @param pushType
	 *            推送环境字符串
	 * @return 生产环境还是正式环境
	 */
	private boolean getIsProduce(final String pushType) {
		// release为正式环境，debug为生产环境
		if (StringUtils.isEmpty(pushType)) {
			return true;
		} else {
			if (StringUtils.equals("release", pushType)) {
				return true;
			} else {
				return false;
			}
		}
	}

}
